package olga.gorbatiuk.perdep.logger.record;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import static olga.gorbatiuk.perdep.logger.util.StringUtils.hasText;
import olga.gorbatiuk.perdep.logger.exceptions.MyIllegalArgumentException;
import static olga.gorbatiuk.perdep.logger.util.StringUtils.hasText;

public final class Record {

    private final Date time;
    private final Importance importance;
    private final String messageSource;
    private final String message;

    public Record(Date time, Importance importance, String messageSource,
            String message) throws MyIllegalArgumentException {
        validateRecord(time, importance, messageSource, message);

        this.time = new Date(time.getTime());
        this.importance = importance;
        this.messageSource = messageSource.replaceAll("\\s+", "");//строка не содержит пробельных символов
        this.message = message.replaceAll("\\n+", " ");// строка не содержит переносов строк

    }

    private void validateRecord(Date time, Importance importance,
            String messageSource, String message) throws MyIllegalArgumentException {

        if (time == null) {
            throw new MyIllegalArgumentException("Time shouldn't be null");
        }
        if ((null == importance)
                || (importance.getStringValue().trim().isEmpty())) {
            throw new MyIllegalArgumentException("Importance shouldn't be null or empty");
        }
        if ((message == null) || (message.trim().isEmpty())) {
            throw new MyIllegalArgumentException("Message shouldn't be null or empty");
        }
        if ((messageSource == null) || (messageSource.trim().isEmpty()) || hasText(messageSource)) {
            throw new MyIllegalArgumentException("Message shouldn't be null "
                    + "or empty and must have at least a one non-whitespace symbols");
        }
    }

    public Record(String errorMessage) throws MyIllegalArgumentException {
        //Можно использовать метод hasText StringUtils
        if ((errorMessage == null) || (errorMessage.trim().isEmpty()) || hasText(errorMessage)) {
            throw new MyIllegalArgumentException("errorMessage shouldn't be null "
                    + "or empty and must have at least a one non-whitespace symbols");
        }
        // заменяем все пробельные символы в строке на один пробел
        String stringWithOneSpaseBetweenWords = errorMessage.trim().replaceAll("\\s+", " ");
        // разделяем строку по пробелам на слова и ложим в массив
        String[] arr = stringWithOneSpaseBetweenWords.split("\\s");

        StringBuilder sb = new StringBuilder();
        // выгребаем из массива строки обозначающие дату и разделяем их пробелом
        sb.append(arr[0]).append(" ").append(arr[1]);
        String dateString = sb.toString();
        Date time = new Date();
        try {
            //Из строки парсим дату по формату
            time = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss").parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        this.time = time;
        this.importance = Importance.fromString(arr[2]);
        this.messageSource = arr[3];

        sb = new StringBuilder();
        for (int i = 4; i < arr.length; i++) {// Оставшиеся строки в массиве - это сообщение. 
            sb.append(arr[i]).append(" ");// Конкатенируем их разделяя пробелами 
        }
        this.message = sb.toString();// и ложим в message
    }

    public Date getTime() {
        return new Date(this.time.getTime());
    }

    public Importance getImportance() {
        return importance;
    }

    public String getMessageSource() {
        return messageSource;
    }

    public String getMessage() {
        return message;
    }

    @Override
    public int hashCode() {
        return Objects.hash(time, importance, messageSource, message);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Record other = (Record) obj;
        if (!Objects.equals(time, other.time)) {
            return false;
        }
        if (!Objects.equals(importance, other.importance)) {
            return false;
        }
        if (!Objects.equals(messageSource, other.messageSource)) {
            return false;
        }
        return Objects.equals(message, other.message);
    }

    @Override
    public String toString() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(
                "yyyy-mm-dd hh:mm:ss");
        return dateFormat.format(time) + " " + importance.getStringValue()
                + " " + messageSource + " " + message;
    }
}
